/*
This file is part of MMM.

MMM is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

MMM is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with MMM.  If not, see <http://www.gnu.org/licenses/>.
*
* @package    MMMTools
* @copyright  2015 High Performance Humanoid Technologies (H2T), Karlsruhe, Germany
*
*/

#include <VirtualRobot/RuntimeEnvironment.h>

#include "ConverterApplicationBaseConfiguration.h"
#include "ConverterApplicationHelper.h"

ConverterApplicationBaseConfiguration::ConverterApplicationBaseConfiguration()
{
    // Please do NOT add default values for parameters because that can be really confusing
    converterLibSearchPaths.push_back(std::string(MMMTools_LIB_DIR));
}

bool ConverterApplicationBaseConfiguration::processCommandLine(int argc, char *argv[])
{
    VirtualRobot::RuntimeEnvironment::considerKey("libPath");

    VirtualRobot::RuntimeEnvironment::considerKey("converter");  // Not changed to converterName for reasons of downward compatibility
    VirtualRobot::RuntimeEnvironment::considerKey("converterConfigFile");

    VirtualRobot::RuntimeEnvironment::considerKey("inputFile");
    VirtualRobot::RuntimeEnvironment::considerKey("markerPrefix");

    VirtualRobot::RuntimeEnvironment::considerKey("sourceModel");  // Not changed to sourceModelFile for reasons of downward compatibility
    VirtualRobot::RuntimeEnvironment::considerKey("sourceModelProcessor");
    VirtualRobot::RuntimeEnvironment::considerKey("sourceModelProcessorConfigFile");

    VirtualRobot::RuntimeEnvironment::considerKey("targetModel");  // Not changed to targetModelFile for reasons of downward compatibility
    VirtualRobot::RuntimeEnvironment::considerKey("targetModelProcessor");
    VirtualRobot::RuntimeEnvironment::considerKey("targetModelProcessorConfigFile");

    VirtualRobot::RuntimeEnvironment::processCommandLine(argc,argv);
    VirtualRobot::RuntimeEnvironment::print();

    setupConverterFactories(converterLibSearchPaths);

    valid = true;

    if (VirtualRobot::RuntimeEnvironment::hasValue("libPath"))
    {
        std::string libpaths = VirtualRobot::RuntimeEnvironment::getValue("libPath");
        std::vector<std::string> strs;
        std::string splitStr = ";,";
        boost::split(strs, libpaths, boost::is_any_of(splitStr));
        converterLibSearchPaths.insert(converterLibSearchPaths.end(), strs.begin(), strs.end());
    }

    converterName = getParameter("converter", false, false);
    if (converterName.empty())
        converterName = "NloptConverter";

    converterConfigFile = getParameter("converterConfigFile", true, true);

    inputFile = getParameter("inputFile", true, true);
    markerPrefix = getParameter("markerPrefix", false, false);

    sourceModelFile = getParameter("sourceModel", false, true);
    sourceModelProcessor = getParameter("sourceModelProcessor", false, false);
    sourceModelProcessorConfigFile = getParameter("sourceModelProcessorConfigFile", false, true);

    if (sourceModelProcessor.empty() != sourceModelProcessorConfigFile.empty())
    {
        MMM_ERROR << "Specify both a source model processor and a source model processor config file or none!" << std::endl;
        return false;
    }

    if (sourceModelFile.empty() && !sourceModelProcessor.empty())
    {
        MMM_ERROR << "Specify a source model if a source model processor is set!" << std::endl;
        return false;
    }

    targetModelFile = getParameter("targetModel", true, true);
    targetModelProcessor = getParameter("targetModelProcessor", false, false);
    targetModelProcessorConfigFile = getParameter("targetModelProcessorConfigFile", false, true);

    if (targetModelProcessor.empty() != targetModelProcessorConfigFile.empty())
    {
        MMM_ERROR << "Specify both a target model processor and a target model processor config file or none!" << std::endl;
        return false;
    }

    inputFileType = UNKNOWN;

    if (inputFile.size() > 3)
    {
        std::string fileExtension = inputFile.substr(inputFile.size() - 3, 3);
        std::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), tolower);

        if (fileExtension == "c3d")
            inputFileType = C3D;
        else if (fileExtension == "xml")
            inputFileType = MMM;
    }

    return valid;
}

void ConverterApplicationBaseConfiguration::print()
{
    std::cout << "Converter name: " << converterName << std::endl;
    std::cout << "Converter config file: " << converterConfigFile << std::endl;
    std::cout << "Input file: " << inputFile << std::endl;
    std::cout << "Marker prefix: " << markerPrefix << std::endl;
    std::cout << "Source model file: " << sourceModelFile << std::endl;
    std::cout << "Source model processor: " << sourceModelProcessor << std::endl;
    std::cout << "Source model processor config file: " << sourceModelProcessorConfigFile << std::endl;
    std::cout << "Target model file: " << targetModelFile << std::endl;
    std::cout << "Target model processor: " << targetModelProcessor << std::endl;
    std::cout << "Target model processor config file: " << targetModelProcessorConfigFile << std::endl;
}

std::string ConverterApplicationBaseConfiguration::getParameter(std::string parameterName, bool required, bool isPath)
{
    if (VirtualRobot::RuntimeEnvironment::hasValue(parameterName))
    {
        std::string value = VirtualRobot::RuntimeEnvironment::getValue(parameterName);

        if (isPath && !VirtualRobot::RuntimeEnvironment::getDataFileAbsolute(value))
        {
            MMM_ERROR << "Invalid path: " << value << std::endl;
            valid = false;
            return "";
        }

        return value;
    }
    else if (required)
    {
        MMM_ERROR << "Missing parameter " << parameterName << "!" << std::endl;
        valid = false;
    }

    return "";
}
